﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;

namespace AppReviewerClient
{

    public static class UrlSiteHelper
    {
        public static string GetUploadVideoUrl(string host)
        {
            return host + "Tester/ExerciseVideo/";
        }

        public static string GetCheckAccountVideoUrl(string host)
        {
            return host + "Account/Login/";
        }

        public static string GetExerciseList(string host)
        {
            return host + "tester/GetTesterExercise/";
        }

        public static string GetCheckUser(string host)
        {
            return host + "User/CheckUser/";
        }
    }
    public static class FilepathHelper
    {
        public const string PartialUploadExtension = "pup";

        private const string ProgramDirectory = "\\AppReviewerClient\\";
        private const string UserDataDirectory = "\\Data\\";
        private const string TempDirectory = "\\Temp\\";

        /// <summary>
        /// Ritorna directory base, se non esiste la crea. 
        /// </summary>
        /// <returns></returns>
        private static string GetProgramDirectoryPath()
        {
            var folderPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + ProgramDirectory;

            if (!Directory.Exists(folderPath))
                Directory.CreateDirectory(folderPath);

            return folderPath;
        }

        /// <summary>
        /// Ritorna directory base, se non esiste la crea. 
        /// </summary>
        /// <returns></returns>
        private static string GetTempDirectoryPath()
        {
            var folderPath = GetProgramDirectoryPath() + TempDirectory;

            if (!Directory.Exists(folderPath))
                Directory.CreateDirectory(folderPath);

            return folderPath;
        }

        public static string GetTempDirectoryPath(int id)
        {
            var rslt = GetTempDirectoryPath() + "\\" + id + "\\";

            if (!Directory.Exists(rslt))
                Directory.CreateDirectory(rslt);

            return rslt;
        }

        /// <summary>
        /// Se esiste cerca la cartella temporanea contentente il file con la classe serializzata dove indica 
        /// lo stato di avanzamento.
        /// </summary>
        /// <returns></returns>
        internal static LocalExercise GetLocalExercise(int exerciseid)
        {
            var filepath = GetStatusFilepath(exerciseid);

            return File.Exists(filepath) ? FileUtility.Deserialize<LocalExercise>(filepath) : null;
        }

        /// <summary>
        /// Aggiorna stato esercizio
        /// </summary>
        internal static void UpdateStatus(ExerciseViewModel viewModel, LocalExerciseStatus localExerciseStatus)
        {
            var filepath = GetStatusFilepath(viewModel.ExerciseId);

            var sLocalExercise = File.Exists(filepath)
                                     ? FileUtility.Deserialize<LocalExercise>(filepath)
                                     : new LocalExercise();

            sLocalExercise.LocalExerciseStatus = localExerciseStatus;
            sLocalExercise.ThreadMessageId = viewModel.ExerciseId;

            FileUtility.SerializeToFile(filepath, sLocalExercise);

        }

        /// <summary>
        /// Ritorna percorso file contentente stato esercizio
        /// </summary>
        /// <param name="username"></param>
        /// <param name="exerciseid"></param>
        /// <returns></returns>
        internal static string GetStatusFilepath(int exerciseid)
        {
            var tempPath = GetTempDirectoryPath(exerciseid);
            var filename = String.Format("{0}.status", exerciseid);

            var filepath = tempPath + filename;

            return filepath;
        }

        private static string GetWorkListFilePath()
        {
            var path = GetProgramDirectoryPath();
            const string filename = "work.queue";

            var filepath = path + filename;

            return filepath;
        }

        internal static QueueWorkList GetFileWorkList()
        {
            var filepath = GetWorkListFilePath();

            return File.Exists(filepath) ? FileUtility.Deserialize<QueueWorkList>(filepath) : new QueueWorkList();
        }

        internal static string GetTempDirectoryPathResult(int id)
        {
            var rslt = GetTempDirectoryPath(id) + "\\result\\";

            if (!Directory.Exists(rslt))
                Directory.CreateDirectory(rslt);

            return rslt;
        }

        internal static void SaveWorkList(QueueWorkList queueWorkList)
        {
            FileUtility.SerializeToFile(GetWorkListFilePath(), queueWorkList);
        }

        // Ritorna filepath del file contenente credenziali
        private static string GetCredentialFilepath()
        {
            var rslt = GetProgramDirectoryPath() + "\\user_credentials.ucred";

            return rslt;

        }
        // Ritorna filepath del file contenente credenziali
        private static string GetPartialDownloadDir(string username)
        {
            var rslt = GetProgramDirectoryPath() + "\\partial_upload\\" + username + "\\";

            if (!Directory.Exists(rslt))
                Directory.CreateDirectory(rslt);

            return rslt;
        }
        // Ritorna filepath del file contenente credenziali
        private static string GetPartialDownloadFilepath(string username, string filename)
        {
            var rslt = GetPartialDownloadDir(username) + String.Format("{0}.pup", filename);

            return rslt;
        }

        private static string GetFirstPartialDownload(string username)
        {
            var dir = GetPartialDownloadDir(username);

            var filepath = Directory.GetFiles(dir, "*." + PartialUploadExtension, SearchOption.AllDirectories).FirstOrDefault();

            return filepath ?? string.Empty;
        }

        internal static Dictionary<string, string> GetCredentials()
        {
            var filepath = GetCredentialFilepath();
            if (File.Exists(filepath))
                return FileUtility.Deserialize<Dictionary<string, string>>(filepath);
            return new Dictionary<string, string>() { { "username", String.Empty }, { "password", String.Empty } };
        }

        internal static void SaveCredentials(string username, string password, bool isCredentialsValid)
        {
            var s = new Dictionary<string, string>() { { "username", username }, { "password", password }, { "valid", isCredentialsValid.ToString(CultureInfo.InvariantCulture) } };

            FileUtility.SerializeToFile(GetCredentialFilepath(), s);

        }

        internal static void SavePartialDownloadInfo(YouTubeUploader.UserState u)
        {
            if (u.ResumeUri != null)
            {
                var filename = u.UploadItem.Title;

                var filepath = GetPartialDownloadFilepath(filename);

                FileUtility.SerializeToFile(filepath, u);

            }
        }

        //internal static void SavePartialDownloadInfo(YouTubeUploader.UserState u)
        //{
        //    var filename = u.ResumeUri.AbsoluteUri;

        //    var filepath = GetPartialDownloadFilepath(filename);

        //    FileUtility.SerializeToFile(filepath, u);
        //}

        internal static void DeleteVideo(string p)
        {
            if (File.Exists(p))
                File.Delete(p);
        }

        internal static object GetPartialUpload(string username)
        {
            var file = GetPartialDownloadDir(username);

        }
    }
    public static class FileUtility
    {
        public static TRet DeepCopy<TRet>(TRet cloneThis)
        {
            var bf = new BinaryFormatter();
            var ms = new MemoryStream();
            bf.Serialize(ms, cloneThis);
            ms.Flush();
            ms.Position = 0;
            return (TRet)bf.Deserialize(ms);
        }

        public static void SerializeToFile<TRet>(string filePath, TRet objectToSerialize)
        {
            Stream stream = File.Open(filePath, FileMode.OpenOrCreate);
            var bformatter = new BinaryFormatter();
            bformatter.Serialize(stream, objectToSerialize);
            stream.Close();
        }

        public static TRet Deserialize<TRet>(string filePath)
        {
            Stream stream = File.Open(filePath, FileMode.Open);
            var bformatter = new BinaryFormatter();
            var o = (TRet)bformatter.Deserialize(stream);
            stream.Close();
            return o;
        }
    }
}
